package com.cos.lession53.common;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @author: COS
 * @time: 2022/3/8 11:20
 * @description:
 *  @Component
 * <bean id="myAdvice" class="....."></bean>
 *  @Aspect
 *  声明这个类是一个切面类,包含切点和增强 统一管理所有aop增强
 *  1. 注解的包扫描
 *  2. aop注解驱动
 *  3. 创建一个类,设置 @@Component和@Aspect
 *  4.创建空方法 上面使用@Pointcut("execution(* com.cos.lession53.services..*.*(..))") 来设置切点表达式
 *  5. 自定义方法
 * @before 前置增强 设置JoinPoint a属性
 * @afterRetrning 后置增强 设置JoinPoint a属性,Object arg 代表方法返回值的属性
 * @Around 环绕增强  设置ProceedingJoinPoint jp 属性 代表获取目标方法信息,以及放行和方法返回值的属性
 * @AfterThrowing 异常增强 设置JoinPoint a属性,Exception e 用于接受目标方法出现的异常信息 的属性
 */
@Component
@Aspect
public class MyAdvice {
    /**
     *
     * @author: COS
     * @return:
     * @time: 2022/3/8 11:24
     * @description: 使用空的方法来设置切点标识,方法名就是切点表达式的名称
     */
    @Pointcut("execution(* com.cos.lession53.services..*.*(..))")
    public void pointCut(){}
    @Pointcut("execution(* com.cos.lession53.services..*.*(java.lang.String))")
    public void pointCut2(){}

    /**
     *
     * @author: COS
     * @return:
     * @time: 2022/3/8 11:25
     * @description:
     * @Before 前置增强
     * "pointCut() 使用这个方法上面的切点表达式
     */
    @Before("pointCut()")
    public void before(JoinPoint a){
        System.out.println("前置增强");
        System.out.println(a.getTarget());
        System.out.println(a.getArgs());
        System.out.println(a.getSignature().getName());
    }
    @Before("pointCut()")
    public void before2(JoinPoint a){
        System.out.println("前置增强22222222222222");
        System.out.println(a.getTarget());
        System.out.println(a.getArgs());
        System.out.println(a.getSignature().getName());
    }

    /**
     *
     * @author: COS
     * @return:
     * @time: 2022/3/8 11:27
     * @description:
     *   @AfterReturning 后置增强
     *          returning 属性方法返回值属性,设置完spring会自动把方法的返回值设置进来使用
     *
     */
    @AfterReturning(value = "pointCut()",returning = "arg")
    public void after(JoinPoint a,Object arg){
        System.out.println("这个是后置增强");
        System.out.println("返回值:"+arg);
    }
    /**
     *
     * @author: COS
     * @return:
     * @time: 2022/3/8 11:32
     * @description:
     *   @Around 环绕增强
     *      ProceedingJoinPoint 放行和获取方法返回值用的属性
     */
    @Around("pointCut()")
    public Object interceptor(ProceedingJoinPoint jp) throws Throwable {
        System.out.println(jp.getSignature().getName());
        System.out.println(jp.getArgs());
        System.out.println("环绕前置增强");
        //proceed 目标方法的返回值
        Object proceed = jp.proceed();
        System.out.println("环绕后置增强");
        System.out.println("这个是方法的返回值:"+proceed);
        return proceed;
//        return null;
    }

    /**
     *
     * @author: COS
     * @return:
     * @time: 2022/3/8 11:37
     * @description:
     * 异常增强
     */
    @AfterThrowing(value = "pointCut()",throwing = "e")
    public void myException(JoinPoint a,Exception e){
        System.err.println(a.getSignature().getName()+"出现异常,异常信息为:"+e.getMessage());
    }


}
